feat(tui,coding-agent): show working/idle agent status in terminal tabs - #1397
feat(tui,coding-agent): show working/idle agent status in terminal tabs#1397MoerAI wants to merge 2 commits into
Conversation
Terminal tabs gave no signal about whether a senpi session was busy or waiting for input, so users had to focus each tab to find out. Emit an event-driven status instead of a spinner (Codex's animated title spins bells under screen and does not animate in tmux, openai/codex#17198): - tui: setTitle() now emits OSC 2 alongside OSC 0. OSC 2 is the sequence Zed documents for terminal titles and tmux/screen derive window names from it, so titles reach more terminals. Extracted as formatTerminalTitleSequence(). - coding-agent: track agent activity and prefix the terminal title with "[working]" on agent_start/compaction_start, returning to the plain title on agent_end/compaction_end/stop. The token leads the title so it survives the truncation tab bars apply. - coding-agent: mirror the status into process.title, since Zed builds its tab label from the foreground process (name + argv), not from OSC. Known limitation: on macOS process.title rewrites argv only (p_comm and proc_pidpath stay "node"), and Zed's pty_info has_changed compares only cwd and name, so Zed will not repaint a tab from an argv-only change. The refreshed argv is still cached, so the tab picks it up on the next repaint. The OSC title reaches Zed breadcrumbs and other terminals' tabs immediately.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d515f03e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * from the OSC title, so argv is the only channel that can reach that label. | ||
| */ | ||
| private applyProcessActivityTitle(): void { | ||
| process.title = formatAgentActivityProcessTitle(this.agentActivityStatus, APP_NAME); |
There was a problem hiding this comment.
Put the status in an argv element Zed reads
When this runs under Zed, assigning process.title rewrites the OS command line as a single argv[0] value such as senpi [working]. The Zed path described here builds the tab label from the executable name plus argv[1..], so neither status token is included; the added test only reads Node's process.title getter and therefore cannot detect this. Consequently the channel introduced specifically for Zed tabs does not surface the status and needs to use data Zed actually reads.
Useful? React with 👍 / 👎.
Review follow-up on the working/idle terminal status. Revert the tui OSC 2 change. The terminal parser Zed/Alacritty use dispatches OSC `0 | 2` to the same set_title handler (alacritty/vte osc_dispatch), so OSC 0 already set the title and the extra sequence and its exported helper were redundant. packages/tui is now untouched. Drop the process.title mirror. Measured against the installed Zed 1.18.1 (tag v1.18.1) and a KERN_PROCARGS2 probe: Zed renders `name + argv[1..]`, while process.title on macOS rewrites argv[0] only, so the status could never reach a Zed tab. name is immutable for a live process, and under Bun the setter does not change argv at all. Zed users see the status in the terminal breadcrumbs; a Zed tab indicator needs a Zed-side feature. Test the real event seams (agent_start, agent_end, compaction_start, compaction_end while streaming, stop) through handleEvent instead of calling the setter directly, so deleting the wiring fails the suite, and restore process.title in afterEach.
What
The interactive mode prefixes the terminal title with
[working]onagent_startandcompaction_start, restoring the plain title onagent_end,compaction_end, andstop.The token leads the title so it survives tab truncation. Idle uses the plain title. Updates are static and event-driven.
Scope:
packages/coding-agent. The existing OSC title transport is unchanged.Tests
The regression tests exercise
handleEventfor agent start/end, compaction start/end, compaction during streaming, andstop(). They also cover title composition, repeated transitions, and preservation ofprocess.title.Removing the event wiring makes 6 of the 9 regression tests fail.
Verification:
npm run check: passed.QA evidence
Artifacts:
local-ignore/qa-evidence/20260906-terminal-tab-agent-status/.The real senpi TUI ran in a node-pty terminal against a local fake model server, in an isolated sandbox without paid model calls. The real
~/.senpi/agent/auth.jsonhash was unchanged.The driver subscribes to PTY output. The fake server holds its response until the working title is observed, then releases the response so completion and return to idle can be checked without fixed sleeps or polling.
Observed OSC title transitions:
results.json:{"passed":7,"total":7,"allPassed":true}.This verifies the emitted title sequence through the real CLI and PTY. Individual terminal applications were not separately driven.
No regression
Title precedence remains active tool hook > tool execution > extension > normal title. The working token is prepended without changing the title content. The existing terminal progress setting and OSC title transport remain unchanged.